package titt.key;

public class SingleWildcardKey implements TITTKey {
	
	private String key = KeyFactory.SEP;
	
	private boolean hasWildcard = false;

	private final String tokens[];
	
	public SingleWildcardKey(String... tokens) {
		for(String s : tokens) {
			if(s.isEmpty()) continue;
			
			if(s.equals(KeyFactory.WILDCARD)) {
				if(!hasWildcard) {
					hasWildcard = true;
					key += s + KeyFactory.SEP;
				}
			}
			else key += s + KeyFactory.SEP;
		}
		this.tokens = tokens;
		this.key = this.key.toLowerCase();
	}
	
	public SingleWildcardKey(String keystr) {
		this(keystr.startsWith(KeyFactory.SEP)? keystr.substring(KeyFactory.SEP.length()).split("\\"+KeyFactory.SEP): keystr.split("\\"+KeyFactory.SEP));
	}
	
	@Override
	public String[] getTokens() {
		return tokens;
	}
	
	@Override
	public String asKeyString() {
		return key;
	}
		
	@Override
	public boolean equals(TITTKey r) {
		return asKeyString().equalsIgnoreCase(r.asKeyString());
	}
		
	@Override
	public boolean equivalentTo(TITTKey r) {
		return equivalentTo(this, r) || equivalentTo(r, this);
	}
	
	@Override
	public boolean containsWildcard() {
		return hasWildcard;
	}
	
	@Override
	public String toString() {
		return asKeyString();
	}
	
	private boolean equivalentTo(TITTKey r1, TITTKey r2) {
		String[] t1 = r1.getTokens(),t2 = r2.getTokens();
		
		if(!r1.containsWildcard()) return linearEquals(t1, t2);

		
		if(t2.length < t1.length && !(t1.length - 1 == t2.length && t1[t1.length-1].equals(KeyFactory.WILDCARD)))	return false;

		
		String[] l = new String[t2.length];
		
		int wc = l.length - t1.length + 1, c = 0;
		for(int i = 0; i < t1.length; i++) {
			if(r1.getTokens()[i].equals(KeyFactory.WILDCARD)) {
				for(int h = 0; h < wc; h++)
					l[c++] = KeyFactory.WILDCARD;
			}
			else l[c++] = t1[i];
		}
				
		return linearEquals(l, t2);
		
	}
	
	private boolean linearEquals(String[] t1, String[] t2) {
		if(t1.length != t2.length) return false;
		for(int i = 0; i < t1.length; i++) {
			if(t1[i].equals(KeyFactory.WILDCARD) || t2[i].equals(KeyFactory.WILDCARD) || t1[i].equalsIgnoreCase(t2[i])) continue;
			return false;
		}
		return true;
	}
		
	@Override
	public int compareTo(TITTKey r) {
		if(this.tokens.length > r.getTokens().length) return -r.compareTo(this);

		for(int i = 0; i < tokens.length; i++) {
			String t1 = this.tokens[i], t2 = r.getTokens()[i];

			if(t1.equals(KeyFactory.WILDCARD) && !t2.equals(KeyFactory.WILDCARD)) return  1;
			if(!t1.equals(KeyFactory.WILDCARD) && t2.equals(KeyFactory.WILDCARD)) return -1;

		}
		
		return - (tokens.length - r.getTokens().length);
	}
	
}
